Repository navigation
fix(rspec): quarantine and abort edge cases (retries, dry-run, before(:context), hook order) - #1213
Conversation
With TRUNK_QUARANTINE_QUERY_FAILURE_EXIT=true, examples after a failed quarantine lookup are skipped from a before(:example) hook. A plain `before` is appended, so any before hooks the suite configured before requiring trunk_spec_helper still ran (DB setup, fixtures, etc.) for an example that was then skipped. Register it with prepend_before so the skip happens first. Hook registration moves into RSpec::Trunk.install(config, run) so it can be exercised against a sandboxed configuration. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
😎 Merged successfully - details. |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #1213 +/- ##
==========================================
+ Coverage 83.74% 83.96% +0.22%
==========================================
Files 74 74
Lines 17745 17749 +4
==========================================
+ Hits 14860 14903 +43
+ Misses 2885 2846 -39 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
|
- Abort + in-place retries: RSpec starts no new examples once wants_to_quit is set, so the abort hook only fired for an example re-run in place by rspec-retry, and its skip replaced the failure: an always-failing example finished pending and the run exited 0. The hook now re-raises the failure that aborted the run. - --dry-run: every example was recorded as passed and uploaded. The listener now records and uploads nothing in a dry run. - before(:context) errors: each example's failure was quarantined, but the group still returned false, failing the run. A group whose examples all passed or are pending now reports as passed. - A quarantined example that failed again in an after hook kept only the last error; failures now accumulate in a MultipleExceptionError. - Start/finish times were truncated to whole seconds. add_test now takes f64 epoch seconds and keeps microseconds. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
@claude review |
Code reviewI found 8 issues. Two can hide real failures and one mis-reports them; the rest are smaller. Bugs1. 2. 3. Smaller issues4. The harness comment is wrong for 5. Re-raising the stored abort failure starts another quarantine lookup (trunk_spec_helper.rb#L89) 6. 7. 8. Checked against rspec-core 3.13.6 and the chrono tags; I didn't run the reproductions. 🤖 Generated with Claude Code |
- A group RSpec failed now passes only when Trunk is active and every example's failure was quarantined. A green status alone let a crashing before(:context) over pending examples (error hidden in pending_exception, status :passed) exit 0 where plain RSpec exits 1. - The abort replays the first failure (the one whose lookup failed), not whichever came last, and the replay skips the quarantine lookup. - Quarantined failures combine within an attempt only; the prepended before hook resets them as each attempt starts. - Comment on the prepended hook no longer claims around hooks are skipped. - timestamp_from_epoch_secs uses prost_wkt_types' From<DateTime<Utc>>. - chrono >= 0.4.35, where DateTime::from_timestamp_micros first appears. - Test harness: FakeReport handles try_save, which CI reaches because it sets TRUNK_LOCAL_UPLOAD_DIR; it also counts lookups. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Summary
This PR started as a one-line switch from
beforetoprepend_beforefor the quarantine-abort hook, which a customer suggested. Reviewing the gem for similar logic errors found five more bugs, and this PR fixes all of them. Each one was reproduced against a locally built gem before being fixed.prepend_before, so it runs ahead of before hooks that were set up beforetrunk_spec_helperwas required.aroundhooks still wrap a skipped example; abeforehook can't prevent that.RSpec.world.wants_to_quitis set. So the abort hook only ever fired when rspec-retry re-ran the same example, and itsskipreplaced the failure. WithTRUNK_QUARANTINE_QUERY_FAILURE_EXIT=trueand rspec-retry, an example that always fails finished as1 example, 0 failures, 1 pendingwith exit 0. The hook now re-raises the first failure that aborted the run, so the retry fails again right away without running the test body. The replayed failure skips the quarantine lookup. Examples that never ran are still skipped.rspec --dry-runuploaded every example as passed. In a dry run RSpec reports each example as passed without running it. The listener now records and uploads nothing whendry_run?is set.before(:context)failure still failed the build. RSpec fails each example throughset_exception, where quarantining applies, but the group itself still returnsfalse, and that sets the exit code. The same quarantined error exited 0 when raised in the test body and 1 when raised inbefore(:context). When Trunk is active and every example's failure was quarantined, the group now reports as passed. A green status alone isn't enough: apendingexample over a crashingbefore(:context)ends up:passedwith the error hidden, and plain RSpec fails that run.afterhook kept only the last error. The recorded failure (trunk_quarantined_exception) was overwritten, so Trunk receivedcleanup errorinstead of the real failure. Failures in the same attempt now accumulate in aMultipleExceptionError, as RSpec does for non-quarantined examples. When an example is re-run in place, each attempt starts fresh.Time#to_i, and Rust built the timestamps with zero nanoseconds.MutTestReport#add_testnow takesf64epoch seconds and keeps microseconds.chrononow requires at least 0.4.35, the first version withDateTime::from_timestamp_micros. Its only callers are the gem and the Rust tests. It is also exported to wasm, wheref64maps to a JS number.Testing
test/quarantine_spec.rbcovers fixes 2–6 and the follow-ups from review, andtest/abort_hook_spec.rbcovers the hook order (1).test/support/trunk_harness.rbruns sandboxed examples with Trunk active against a fake report, so no API is needed. I checked that each new example fails when its fix is reverted. The suite also passes withTRUNK_LOCAL_UPLOAD_DIRset, as it is in CI.bundle exec rake test: 34 examples, 0 failures. That includesnamespace_spec, so the newExampleGrouppatch adds nothing outsideRSpec::Trunk.cargo test -p test_reportpasses, including new unit tests for the timestamp conversion.cargo fmt --checkis clean, andcargo check -p test_report --features wasmbuilds.--dry-run, and a quarantine answer stubbed on the report:before(:context)failure: exit 0 (was 1)before(:context)over apendingexample: exit 1, the same as plain RSpecafterhook error: both errors reported🤖 Generated with Claude Code